import { getEnv, getStorageSync, hideLoading, removeStorageSync, showModal, useRouter } from '@tarojs/taro'
import { NativeHttp, isFlutterApp } from 'taro-bridge'
import Canceler from './canceler'
import type { RequestOptions, ResponseBody } from './types'
import { Request as H5Req } from './http'
import { queue } from './queue'
import { getUserATicket, refreshToken } from './utils'
import { APP_CODE_KEY, AUTH_TICKET_KEY, CLIENT_CHANNEL, HOS_CODE_KEY, R_A_TOKEN, USER_TICKET_KEY } from '@/constants/key'
import { goLogin } from '@/router/jump'
import { browserJudgment, decodeUrlParams } from '@/utils'
import { Toast } from '@/utils/message'

export enum ResCode {
  CANCEL = -1,
  SUCCESS = 0,
  INVALID_TOKEN = 301,
  /**
   * 订单不存在
   */
  ORDER_NOT_EXISTS = 4001,
  /**
   * 报告不存在
   */
  REPORT_NOT_EXISTS = 4901,
  COMMON_ALERT = 9001,
  COMMON_ERROR = 10000,
  // 就诊人信息不完善
  PATIENT_PERFECT = 5001,
  /**
   * 未进行小程序openid授权
   */
  UN_AUTH = 101,
  /**
   * 未登录
   */
  UN_LOGIN = 103,
  /**
   * 授权过期
   */
  AUTH_CODE_EXPIRE = 111,
  /**
   * 预交金余额不足
   */
  IN_BALANC = 324,
}

const Http = isFlutterApp() ? NativeHttp : H5Req
function clientChannel() {
  if (process.env.TARO_ENV === 'weapp')
    return 'WECHAT_MP'
  if (process.env.TARO_ENV === 'alipay')
    return 'ALI_MP'
  if (process.env.TARO_ENV === 'h5') {
    if (browserJudgment() === 'weapp')
      return 'WECHAT_OFFICIAL'
    else if (browserJudgment() === 'alipay')
      return 'ALI_MP'

    else
      return 'WEBSITE'
  }
}
export const Request = new Http({
  config: {
    headers: {
      'Content-Type': 'application/json;charset=UTF-8',
    },
    errorTips: true,
    baseURL: getEnv() === 'WEB' ? '/api/mobile' : `${process.env.TARO_REQUEST_URL}`,
    uploadURL: `${process.env.TARO_UPLOAD_HOST}`,
  },
  requestInterceptor: (config) => {
    const { ticket } = decodeUrlParams(useRouter().params) as Recordable
    config.headers[AUTH_TICKET_KEY] = getStorageSync(AUTH_TICKET_KEY)
    config.headers[HOS_CODE_KEY] = `${process.env.TARO_HOS_CODE}`
    config.headers[USER_TICKET_KEY] = ticket || getStorageSync(USER_TICKET_KEY)
    config.headers[R_A_TOKEN] = getStorageSync(R_A_TOKEN)
    config.headers[CLIENT_CHANNEL] = clientChannel()
    config.headers[APP_CODE_KEY] = `${process.env.TARO_APP_CODE}`
    return config
  },
  async responseCallback<T>(response: ResponseBody<T>, resolve: (value: T | PromiseLike<T>) => void, reject: (reason?: any) => void, opts: RequestOptions) {
    const { code, data, message } = response

    switch (code) {
      case ResCode.SUCCESS:
        resolve(data)
        break

      case ResCode.PATIENT_PERFECT:
        resolve(response as T)
        break

      case ResCode.UN_AUTH:
        queue.add(opts, resolve, reject)
        if (!queue.isPending) {
          queue.isPending = true
          const res = await getUserATicket()
          if (res) {
            queue.isPending = false
            queue.exec()
          }
        }
        break
      case ResCode.AUTH_CODE_EXPIRE:
        window.location.replace(`${process.env.TARO_SERVER_URL}/zhongri/app/#/zhongri/app/pages/auth/index?url=${encodeURIComponent(window.location.href)}`)
        break

      case ResCode.INVALID_TOKEN:
        queue.add(opts, resolve, reject)
        if (!queue.isPending) {
          queue.isPending = true
          const res = await refreshToken(data)
          if (res) {
            queue.isPending = false
            queue.exec()
          }
        }
        break
      case ResCode.UN_LOGIN:
        Canceler.removeAll()
        removeStorageSync(USER_TICKET_KEY)
        if (!useRouter().params.redirect)
          goLogin()

        break

      case ResCode.CANCEL:
        reject({})
        break

      default:
        reject(response)
    }

    if (!opts.errorTips || !message)
      return

    if (code === ResCode.COMMON_ERROR)
      Toast(message).then(() => hideLoading())

    if (code === ResCode.COMMON_ALERT) {
      showModal({
        title: '提示',
        content: message,
        showCancel: false,
        confirmColor: '#6582F9',
      })
    }
  },
})
